package config

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"

	"github.com/joho/godotenv"
	"github.com/spf13/viper"
)

// Config 全局配置结构
type Config struct {
	App           AppConfig           `mapstructure:"app"`
	Server        ServerConfig        `mapstructure:"server"`
	Database      DatabaseConfig      `mapstructure:"database"`
	Redis         RedisConfig         `mapstructure:"redis"`
	MongoDB       MongoDBConfig       `mapstructure:"mongodb"`
	Elasticsearch ElasticsearchConfig `mapstructure:"elasticsearch"`
	Milvus        MilvusConfig        `mapstructure:"milvus"`
	JWT           JWTConfig           `mapstructure:"jwt"`
	AI            AIConfig            `mapstructure:"ai"`
	Log           LogConfig           `mapstructure:"log"`
	Tracing       TracingConfig       `mapstructure:"tracing"`
	Monitoring    MonitoringConfig    `mapstructure:"monitoring"`
	Storage       StorageConfig       `mapstructure:"storage"`
	Cache         CacheConfig         `mapstructure:"cache"`
	RateLimit     RateLimitConfig     `mapstructure:"rateLimit"`
	Security      SecurityConfig      `mapstructure:"security"`
}

type AppConfig struct {
	Name        string `mapstructure:"name"`
	Version     string `mapstructure:"version"`
	Environment string `mapstructure:"environment"`
	Debug       bool   `mapstructure:"debug"`
}

type ServerConfig struct {
	Host         string `mapstructure:"host"`
	Port         int    `mapstructure:"port"`
	ReadTimeout  int    `mapstructure:"readTimeout"`
	WriteTimeout int    `mapstructure:"writeTimeout"`
	IdleTimeout  int    `mapstructure:"idleTimeout"`
}

type DatabaseConfig struct {
	Host            string `mapstructure:"host"`
	Port            int    `mapstructure:"port"`
	User            string `mapstructure:"user"`
	Password        string `mapstructure:"password"`
	Name            string `mapstructure:"name"`
	Charset         string `mapstructure:"charset"` // MySQL字符集
	MaxOpenConns    int    `mapstructure:"maxOpenConns"`
	MaxIdleConns    int    `mapstructure:"maxIdleConns"`
	ConnMaxLifetime int    `mapstructure:"connMaxLifetime"`
}

type RedisConfig struct {
	Host     string `mapstructure:"host"`
	Port     int    `mapstructure:"port"`
	Password string `mapstructure:"password"`
	DB       int    `mapstructure:"db"`
	PoolSize int    `mapstructure:"poolSize"`
}

type MongoDBConfig struct {
	Host     string `mapstructure:"host"`
	Port     int    `mapstructure:"port"`
	User     string `mapstructure:"user"`
	Password string `mapstructure:"password"`
	Database string `mapstructure:"database"`
}

type ElasticsearchConfig struct {
	URL      string `mapstructure:"url"`
	Username string `mapstructure:"username"`
	Password string `mapstructure:"password"`
}

type MilvusConfig struct {
	Host string `mapstructure:"host"`
	Port int    `mapstructure:"port"`
}

type JWTConfig struct {
	Secret    string `mapstructure:"secret"`
	ExpiresIn string `mapstructure:"expiresIn"`
}

type AIConfig struct {
	OpenAI    OpenAIConfig    `mapstructure:"openai"`
	Anthropic AnthropicConfig `mapstructure:"anthropic"`
	Ollama    OllamaConfig    `mapstructure:"ollama"`
	Local     LocalConfig     `mapstructure:"local"`
	Default   DefaultConfig   `mapstructure:"default"`
	Models    []ModelConfig   `mapstructure:"models"`
}

type OpenAIConfig struct {
	APIKey  string `mapstructure:"apiKey"`
	BaseURL string `mapstructure:"baseUrl"`
	Model   string `mapstructure:"model"`
	Enabled bool   `mapstructure:"enabled"`
}

type AnthropicConfig struct {
	APIKey  string `mapstructure:"apiKey"`
	BaseURL string `mapstructure:"baseUrl"`
	Model   string `mapstructure:"model"`
	Enabled bool   `mapstructure:"enabled"`
}

type OllamaConfig struct {
	BaseURL string `mapstructure:"baseUrl"`
	Model   string `mapstructure:"model"`
	Enabled bool   `mapstructure:"enabled"`
}

type LocalConfig struct {
	ModelPath string `mapstructure:"modelPath"`
	Model     string `mapstructure:"model"`
	Enabled   bool   `mapstructure:"enabled"`
}

type DefaultConfig struct {
	Provider string `mapstructure:"provider"`
	Model    string `mapstructure:"model"`
}

type ModelConfig struct {
	ID          string                 `mapstructure:"id"`
	Provider    string                 `mapstructure:"provider"`
	Model       string                 `mapstructure:"model"`
	Name        string                 `mapstructure:"name"`
	Description string                 `mapstructure:"description"`
	Enabled     bool                   `mapstructure:"enabled"`
	Priority    int                    `mapstructure:"priority"`
	Config      map[string]interface{} `mapstructure:"config"`
}

type LogConfig struct {
	Level  string `mapstructure:"level"`
	Format string `mapstructure:"format"`
}

type TracingConfig struct {
	JaegerEndpoint string `mapstructure:"jaegerEndpoint"`
	ServiceName    string `mapstructure:"serviceName"`
}

type MonitoringConfig struct {
	PrometheusEnabled bool `mapstructure:"prometheusEnabled"`
	MetricsPort       int  `mapstructure:"metricsPort"`
}

type StorageConfig struct {
	UploadPath    string `mapstructure:"uploadPath"`
	MaxUploadSize string `mapstructure:"maxUploadSize"`
}

type CacheConfig struct {
	TTL    int    `mapstructure:"ttl"`
	Prefix string `mapstructure:"prefix"`
}

type RateLimitConfig struct {
	Enabled bool `mapstructure:"enabled"`
	RPS     int  `mapstructure:"rps"`
	Burst   int  `mapstructure:"burst"`
}

type SecurityConfig struct {
	CORSAllowedOrigins []string `mapstructure:"corsAllowedOrigins"`
	CORSAllowedMethods []string `mapstructure:"corsAllowedMethods"`
	CORSAllowedHeaders []string `mapstructure:"corsAllowedHeaders"`
}

var GlobalConfig *Config

// LoadConfig 加载配置文件
func LoadConfig(configPath string) (*Config, error) {
	// 加载.env文件
	if err := godotenv.Load(); err != nil {
		log.Printf("Warning: .env file not found: %v", err)
	}

	v := viper.New()

	// 设置配置文件
	if configPath != "" {
		v.SetConfigFile(configPath)
	} else {
		v.SetConfigName("config")
		v.SetConfigType("yaml")
		v.AddConfigPath("./configs")
		v.AddConfigPath("../configs")
		v.AddConfigPath("../../configs")
		v.AddConfigPath("../../../configs")
	}

	// 自动读取环境变量
	v.AutomaticEnv()
	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

	// 读取配置文件
	if err := v.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			log.Printf("Warning: config file not found, using environment variables")
		} else {
			return nil, fmt.Errorf("error reading config file: %w", err)
		}
	}

	// 设置默认值
	setDefaultValues(v)

	var config Config
	if err := v.Unmarshal(&config); err != nil {
		return nil, fmt.Errorf("error unmarshaling config: %w", err)
	}

	// 验证配置
	if err := validateConfig(&config); err != nil {
		return nil, fmt.Errorf("config validation error: %w", err)
	}

	GlobalConfig = &config
	return &config, nil
}

// setDefaultValues 设置默认配置值
func setDefaultValues(v *viper.Viper) {
	v.SetDefault("app.name", "yanxue_ai_go")
	v.SetDefault("app.version", "1.0.0")
	v.SetDefault("app.environment", "development")
	v.SetDefault("app.debug", true)

	v.SetDefault("server.host", "0.0.0.0")
	v.SetDefault("server.port", 8080)
	v.SetDefault("server.readTimeout", 30)
	v.SetDefault("server.writeTimeout", 30)
	v.SetDefault("server.idleTimeout", 120)

	v.SetDefault("database.host", "localhost")
	v.SetDefault("database.port", 3306)
	v.SetDefault("database.user", "root")
	v.SetDefault("database.password", "password")
	v.SetDefault("database.name", "yanxue_ai")
	v.SetDefault("database.charset", "utf8mb4")
	v.SetDefault("database.maxOpenConns", 25)
	v.SetDefault("database.maxIdleConns", 25)
	v.SetDefault("database.connMaxLifetime", 300)

	v.SetDefault("redis.host", "localhost")
	v.SetDefault("redis.port", 6379)
	v.SetDefault("redis.password", "")
	v.SetDefault("redis.db", 0)
	v.SetDefault("redis.poolSize", 10)

	v.SetDefault("mongodb.host", "localhost")
	v.SetDefault("mongodb.port", 27017)
	v.SetDefault("mongodb.user", "admin")
	v.SetDefault("mongodb.password", "password")
	v.SetDefault("mongodb.database", "yanxue_ai")

	v.SetDefault("elasticsearch.url", "http://localhost:9200")
	v.SetDefault("elasticsearch.username", "")
	v.SetDefault("elasticsearch.password", "")

	v.SetDefault("milvus.host", "localhost")
	v.SetDefault("milvus.port", 19530)

	v.SetDefault("jwt.secret", "your-jwt-secret-key")
	v.SetDefault("jwt.expiresIn", "24h")

	// AI配置默认值
	v.SetDefault("ai.openai.apiKey", "")
	v.SetDefault("ai.openai.baseUrl", "https://api.openai.com/v1")
	v.SetDefault("ai.openai.model", "gpt-3.5-turbo")
	v.SetDefault("ai.openai.enabled", true)

	v.SetDefault("ai.anthropic.apiKey", "")
	v.SetDefault("ai.anthropic.baseUrl", "https://api.anthropic.com")
	v.SetDefault("ai.anthropic.model", "claude-3-sonnet-20240229")
	v.SetDefault("ai.anthropic.enabled", false)

	v.SetDefault("ai.ollama.baseUrl", "http://localhost:11434")
	v.SetDefault("ai.ollama.model", "llama2")
	v.SetDefault("ai.ollama.enabled", false)

	v.SetDefault("ai.local.modelPath", "./models")
	v.SetDefault("ai.local.model", "local-model")
	v.SetDefault("ai.local.enabled", false)

	v.SetDefault("ai.default.provider", "openai")
	v.SetDefault("ai.default.model", "gpt-3.5-turbo")

	v.SetDefault("log.level", "info")
	v.SetDefault("log.format", "json")

	v.SetDefault("tracing.jaegerEndpoint", "http://localhost:14268/api/traces")
	v.SetDefault("tracing.serviceName", "yanxue_ai_go")

	v.SetDefault("monitoring.prometheusEnabled", true)
	v.SetDefault("monitoring.metricsPort", 9090)

	v.SetDefault("storage.uploadPath", "./uploads")
	v.SetDefault("storage.maxUploadSize", "10MB")

	v.SetDefault("cache.ttl", 3600)
	v.SetDefault("cache.prefix", "yanxue:")

	v.SetDefault("rateLimit.enabled", true)
	v.SetDefault("rateLimit.rps", 100)
	v.SetDefault("rateLimit.burst", 200)

	v.SetDefault("security.corsAllowedOrigins", []string{"*"})
	v.SetDefault("security.corsAllowedMethods", []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"})
	v.SetDefault("security.corsAllowedHeaders", []string{"*"})
}

// validateConfig 验证配置
func validateConfig(config *Config) error {
	if config.App.Name == "" {
		return fmt.Errorf("app name is required")
	}

	if config.Server.Port <= 0 || config.Server.Port > 65535 {
		return fmt.Errorf("invalid server port: %d", config.Server.Port)
	}

	if config.Database.Host == "" {
		return fmt.Errorf("database host is required")
	}

	if config.JWT.Secret == "" || config.JWT.Secret == "your-jwt-secret-key" {
		return fmt.Errorf("JWT secret must be set and not use default value")
	}

	return nil
}

// GetConfigPath 获取配置文件路径
func GetConfigPath() string {
	if path := os.Getenv("CONFIG_PATH"); path != "" {
		return path
	}

	// 查找配置文件
	configPaths := []string{
		"./configs/config.yml",
		"../configs/config.yml",
		"../../configs/config.yml",
	}

	for _, path := range configPaths {
		if _, err := os.Stat(path); err == nil {
			abs, _ := filepath.Abs(path)
			return abs
		}
	}

	return ""
}
